<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<style>
			
		</style>
	</head>
	<body>
		<input />
		<button>按钮1~</button>
		<button>按钮2~</button>
		<script src="https://cdn.bootcss.com/rxjs/6.0.0-alpha.3/Rx.min.js"></script>
		<script>
			// 纯净性 (Purity)
			// 使用 RxJS 的话，你会将应用状态隔离出来。
			// scan 操作符的工作原理与数组的 reduce 类似。它需要一个暴露给回调函数当参数的初始值。
			// 每次回调函数运行后的返回值会作为下次回调函数运行时的参数。
			// var button = document.querySelector('button');
			// Rx.Observable.fromEvent(button, 'click')
			//   .scan(count => count + 1, 0)
			//   .subscribe(count => console.log(`Clicked ${count} times`));
			// 流动性 (Flow)
			// var button = document.querySelector('button');
			// Rx.Observable.fromEvent(button, 'click')
			//   .throttleTime(1000)
			//   .scan(count => count + 1, 0)
			//   .subscribe(count => console.log(`Clicked ${count} times`));
			// 值 (Values)
			// var button = document.querySelector('button');
			// Rx.Observable.fromEvent(button, 'click')
			//   .throttleTime(1000)
			//   .map(event => event.clientX)
			//   .scan((count, clientX) => count + clientX, 0)
			//   .subscribe(count => console.log(count));
			
			// Observable (可观察对象)
			// var observable = Rx.Observable.create(function (observer) {
			//   observer.next(1);
			//   observer.next(2);
			//   observer.next(3);
			//   setTimeout(() => {
			//     observer.next(4);
			//     observer.complete();
			//   }, 1000);
			// });
			
			// console.log('just before subscribe');
			// observable.subscribe({
			//   next: x => console.log('got value ' + x),
			//   error: err => console.error('something wrong occurred: ' + err),
			//   complete: () => console.log('done'),
			// });
			// console.log('just after subscribe');
			
			// Observables 作为函数的泛化
			// 订阅 Observable 类似于调用函数。
			// var foo = Rx.Observable.create(function (observer) {
			//   console.log('Hello');
			//   observer.next(42);
			// });
			
			// foo.subscribe(function (x) {
			//   console.log(x);
			// });
			// foo.subscribe(function (y) {
			//   console.log(y);
			// });
			
			// foo 的订阅完全是同步的，就像函数一样。
			// var foo = Rx.Observable.create(function (observer) {
			//   console.log('Hello');
			//   observer.next(42);
			//   observer.next(100); // “返回”另外一个值
			//   observer.next(200); // 还可以再“返回”值
			// });
			
			// console.log('before');
			// foo.subscribe(function (x) {
			//   console.log(x);
			// });
			// console.log('after');
			
			// 但你也可以异步地“返回”值：
			// var foo = Rx.Observable.create(function (observer) {
			//   console.log('Hello');
			//   observer.next(42);
			//   observer.next(100);
			//   observer.next(200);
			//   setTimeout(() => {
			//     observer.next(300); // 异步执行
			//   }, 1000);
			// });
			
			// console.log('before');
			// foo.subscribe(function (x) {
			//   console.log(x);
			// });
			// console.log('after');
			
			// func.call() 意思是 "同步地给我一个值"
			// observable.subscribe() 意思是 "给我任意数量的值，无论是同步还是异步"
			
			// Observable 剖析
			// 创建 Observables
			// Observables 可以使用 create 来创建, 但通常我们
			// 使用所谓的创建操作符, 像 of、from、interval、等等。
			// var observable = Rx.Observable.create(function subscribe(observer) {
			//   var id = setInterval(() => {
			//     observer.next('hi')
			//   }, 1000);
			// });
			
			// 示例中的 Observable 对象 observable 可以订阅，像这样：
			// 订阅 Observable 像是调用函数, 并提供接收数据的回调函数。
			// observable.subscribe(x => console.log(x));
			
			// 执行 Observables
			// 在 Observable 执行中, 可能会发送零个到无穷多个 "Next" 通知。如果发送的是 "Error" 或 "Complete" 通知的话，那么之后不会再发送任何通知了。
			// var observable = Rx.Observable.create(function subscribe(observer) {
			//   observer.next(1);
			//   observer.next(2);
			//   observer.next(3);
			//   observer.complete();
			// });
			
			// 清理 Observable 执行
			// var observable = Rx.Observable.from([10, 20, 30]);
			// var subscription = observable.subscribe(x => console.log(x));
			// // 稍后：
			// subscription.unsubscribe();
			
			// function subscribe(observer) {
			//   var intervalID = setInterval(() => {
			//     observer.next('hi');
			//   }, 1000);
			
			//   return function unsubscribe() {
			//     clearInterval(intervalID);
			//   };
			// }
			
			// var unsubscribe = subscribe({next: (x) => console.log(x)});
			
			// // 稍后：
			// unsubscribe(); // 清理资源
			
			// Observer (观察者)
			// var observer = {
			//   next: x => console.log('Observer got a next value: ' + x),
			//   error: err => console.error('Observer got an error: ' + err),
			//   complete: () => console.log('Observer got a complete notification'),
			// };
			// observable.subscribe(observer);
			// var observer = {};
			// observable.subscribe(
			//   x => console.log('Observer got a next value: ' + x),
			//   err => console.error('Observer got an error: ' + err),
			//   () => console.log('Observer got a complete notification')
			// );
			
			// Subscription (订阅)
			// var observable = Rx.Observable.interval(1000);
			// var subscription = observable.subscribe(x => console.log(x));
			// // 稍后：
			// // 这会取消正在进行中的 Observable 执行
			// // Observable 执行是通过使用观察者调用 subscribe 方法启动的
			// subscription.unsubscribe();
			
			// Subscription 还可以合在一起，这样一个 Subscription 调用 unsubscribe() 方法，
			// 可能会有多个 Subscription 取消订阅 。
			// var observable1 = Rx.Observable.interval(400);
			// var observable2 = Rx.Observable.interval(300);

			// var subscription = observable1.subscribe(x => console.log('first: ' + x));
			// var childSubscription = observable2.subscribe(x => console.log('second: ' + x));

			// subscription.add(childSubscription);

			// setTimeout(() => {
			//   // subscription 和 childSubscription 都会取消订阅
			//   subscription.unsubscribe();
			// }, 1000);
			
			// Subject (主体)
			// RxJS Subject 是一种特殊类型的 Observable，它允许将值多播给多个观察者，所以 Subject 是多播的，而普通的 Observables 
			// 是单播的(每个已订阅的观察者都拥有 Observable 的独立执行)。
			// Subject 像是 Observable，但是可以多播给多个观察者。Subject 还像是 EventEmitters，维护着多个监听器的注册表。
			// var subject = new Rx.Subject();
			
			// subject.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			// subject.subscribe({
			//   next: (v) => console.log('observerB: ' + v)
			// });
			
			// subject.next(1);
			// subject.next(2);
			
			// var subject = new Rx.Subject();
			
			// subject.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			// subject.subscribe({
			//   next: (v) => console.log('observerB: ' + v)
			// });
			
			// var observable = Rx.Observable.from([1, 2, 3]);
			
			// observable.subscribe(subject); // 你可以提供一个 Subject 进行订阅
			
			// 多播的 Observables
			// “多播 Observable” 通过 Subject 来发送通知，这个 Subject 可能有多个订阅者，
			// 然而普通的 “单播 Observable” 只发送通知给单个观察者。
			// 多播 Observable 在底层是通过使用 Subject 使得多个观察者可以看见同一个 Observable 执行。
			
			// 在底层，这就是 multicast 操作符的工作原理：观察者订阅一个基础的 Subject，
			//然后 Subject 订阅源 Observable 。下面的示例与前面使用 observable.subscribe(subject) 的示例类似：
			// var source = Rx.Observable.from([1, 2, 3]);
			// var subject = new Rx.Subject();
			// var multicasted = source.multicast(subject);
			
			// // 在底层使用了 `subject.subscribe({...})`:
			// multicasted.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			// multicasted.subscribe({
			//   next: (v) => console.log('observerB: ' + v)
			// });
			
			// // 在底层使用了 `source.subscribe(subject)`:
			// multicasted.connect();
			
			// 请考虑以下示例，下面的列表概述了 Subscriptions 发生的经过：
			
			// 第一个观察者订阅了多播 Observable
			// 多播 Observable 已连接
			// next 值 0 发送给第一个观察者
			// 第二个观察者订阅了多播 Observable
			// next 值 1 发送给第一个观察者
			// next 值 1 发送给第二个观察者
			// 第一个观察者取消了多播 Observable 的订阅
			// next 值 2 发送给第二个观察者
			// 第二个观察者取消了多播 Observable 的订阅
			
			// var source = Rx.Observable.interval(500);
			// var subject = new Rx.Subject();
			// var multicasted = source.multicast(subject);
			// var subscription1, subscription2, subscriptionConnect;
			
			// subscription1 = multicasted.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			// // 这里我们应该调用 `connect()`，因为 `multicasted` 的第一个
			// // 订阅者关心消费值
			// subscriptionConnect = multicasted.connect();
			
			// setTimeout(() => {
			//   subscription2 = multicasted.subscribe({
			//     next: (v) => console.log('observerB: ' + v)
			//   });
			// }, 600);
			
			// setTimeout(() => {
			//   subscription1.unsubscribe();
			// }, 1200);
			
			// // 这里我们应该取消共享的 Observable 执行的订阅，
			// // 因为此后 `multicasted` 将不再有订阅者
			// setTimeout(() => {
			//   subscription2.unsubscribe();
			//   subscriptionConnect.unsubscribe(); // 用于共享的 Observable 执行
			// }, 2000);
			
			// refCount 的作用是，当有第一个订阅者时，多播 Observable 会自动地启动执行，而当最后一个订阅者离开时，多播 Observable 会自动地停止执行。
			// var source = Rx.Observable.interval(500);
			// var subject = new Rx.Subject();
			// var refCounted = source.multicast(subject).refCount();
			// var subscription1, subscription2, subscriptionConnect;
			
			// // 这里其实调用了 `connect()`，
			// // 因为 `refCounted` 有了第一个订阅者
			// console.log('observerA subscribed');
			// subscription1 = refCounted.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			
			// setTimeout(() => {
			//   console.log('observerB subscribed');
			//   subscription2 = refCounted.subscribe({
			//     next: (v) => console.log('observerB: ' + v)
			//   });
			// }, 600);
			
			// setTimeout(() => {
			//   console.log('observerA unsubscribed');
			//   subscription1.unsubscribe();
			// }, 1200);
			
			// // 这里共享的 Observable 执行会停止，
			// // 因为此后 `refCounted` 将不再有订阅者
			// setTimeout(() => {
			//   console.log('observerB unsubscribed');
			//   subscription2.unsubscribe();
			// }, 2000);
			
			// BehaviorSubject
			// BehaviorSubjects 适合用来表示“随时间推移的值”。举例来说，生日的流是一个 Subject，但年龄的流应该是一个 BehaviorSubject 。
			// var subject = new Rx.BehaviorSubject(0); // 0是初始值
			
			// subject.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			
			// subject.next(1);
			// subject.next(2);
			
			// subject.subscribe({
			//   next: (v) => console.log('observerB: ' + v)
			// });
			
			// subject.next(3);
			
			// ReplaySubject
			// ReplaySubject 记录 Observable 执行中的多个值并将其回放给新的订阅者。
			// var subject = new Rx.ReplaySubject(3); // 为新的订阅者缓冲3个值
			
			// subject.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			
			// subject.next(1);
			// subject.next(2);
			// subject.next(3);
			// subject.next(4);
			
			// subject.subscribe({
			//   next: (v) => console.log('observerB: ' + v)
			// });
			
			// subject.next(5);
			
			// 除了缓冲数量，你还可以指定 window time (以毫秒为单位)来确定多久之前的值可以记录。
			// 在下面的示例中，我们使用了较大的缓存数量100，但 window time 参数只设置了500毫秒。
			// var subject = new Rx.ReplaySubject(100, 500 /* windowTime */);
			
			// subject.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			
			// var i = 1;
			// setInterval(() => subject.next(i++), 200);
			
			// setTimeout(() => {
			//   subject.subscribe({
			//     next: (v) => console.log('observerB: ' + v)
			//   });
			// }, 1000);
			
			// AsyncSubject
			// var subject = new Rx.AsyncSubject();
			
			// subject.subscribe({
			//   next: (v) => console.log('observerA: ' + v)
			// });
			
			// subject.next(1);
			// subject.next(2);
			// subject.next(3);
			// subject.next(4);
			
			// subject.subscribe({
			//   next: (v) => console.log('observerB: ' + v)
			// });
			
			// subject.next(5);
			// subject.complete();
			
			// Operators (操作符)
			// function multiplyByTen(input) {
			//   var output = Rx.Observable.create(function subscribe(observer) {
			//     input.subscribe({
			//       next: (v) => observer.next(10 * v),
			//       error: (err) => observer.error(err),
			//       complete: () => observer.complete()
			//     });
			//   });
			//   return output;
			// }
			
			// var input = Rx.Observable.from([1, 2, 3, 4]);
			// var output = multiplyByTen(input);
			// output.subscribe(x => console.log(x));
		</script>
	</body>
</html>
